Master the top 190+ Java interview questions, covering fundamental to advanced topics designed to help both freshers and experienced professionals.
OVERVIEW
Java is a widely used programming language known for its simplicity, robustness, and versatility in developing desktop, web, and mobile applications. Its consistent demand in the tech industry makes mastering Java crucial for career growth.
Preparing for Java interview questions is essential to demonstrate your technical expertise and problem-solving skills. By reviewing these questions, you can effectively showcase your knowledge, boost your confidence, and make a strong impression on potential employers. This focused preparation ensures you align with industry expectations and stand out in the competitive job market.
Download Java Interview Questions
Note : We have compiled all the Java Interview Questions for your reference in a template format. Check it out now!
This section covers key Java interview questions designed for beginners or those with a foundational knowledge of the language. These questions emphasize core concepts, including what Java is, its primary features, and basic operations, providing a solid starting point for mastering the language.
Some of the most important Java interview questions that are asked to freshers are listed below.
Java is a class-based, object-oriented programming language designed to reduce implementation dependencies. It enables developers to write code once and run it anywhere, meaning Java code can execute on all Java-enabled platforms without requiring recompilation. This foundational concept is often asked in most of the Java interview questions.
Yes, Java is platform-independent. This is one of the most commonly asked Java interview questions.
Java’s platform independence means its compiled bytecode can be executed on any operating system. When a program is written in human-readable language, it includes words and phrases machines can't understand. The source code must be converted into a machine-level language for the machine to execute it. The compiler is responsible for translating this high-level language into a format that machines understand.
Thus, a compiler translates a program’s source code into executable code. This code can be machine-level instructions or an intermediate representation, like Java Bytecode, that is interpreted by a virtual machine.
Java has many features which are frequently highlighted in most of the Java interview questions.
Some of its core features are:
In this section of fresher-level Java interview questions, one of the most common questions asked is how Java is different from C++.
Below is a table highlighting the primary differences:
Characteristics | Java | C++ |
---|---|---|
Memory Management | Automatic garbage collection. | Manual memory management using pointers. |
Multiple Inheritance | Supports multiple interface inheritance only. | Supports multiple-class inheritance. |
Platform Dependency | Platform independent (Write once, run anywhere). | Platform dependent requires recompilation. |
Operator Overloading | Not supported | Supported |
Default Parameter | Not supported | Supported |
Language Type | Pure object-oriented | Hybrid (procedural and object-oriented). |
The Java Virtual Machine (JVM) is a runtime engine that enables Java’s Write Once, Run Anywhere capability, a frequent topic that appears in most of the Java interview questions. The JVM interprets Java Bytecode and executes it on any platform, ensuring that Java programs can run seamlessly across operating systems.
The Just-in-time (JIT) compiler is a component within the Java Virtual Machine (JVM) that translates frequently executed sections, or hot spots, in bytecode into machine code that the hardware can understand. The primary purpose of the JIT compiler is to optimize performance for these parts of the code.
Java code is initially compiled by the Java compiler (javac) into bytecode that is designed specifically for the JVM. The JVM then interprets this bytecode and executes it on the underlying hardware. When the JVM identifies certain parts of the code that need to be executed repeatedly, it marks them as hot spots.
For these hot spots, the JVM uses the JIT compiler to further compile the bytecode down to native machine code. Once this compilation is done, the JVM can reuse the optimized, compiled code whenever it needs to execute those sections. JVM is a key topic, and it's often featured in most of the Java interview questions.
Java is pass-by-value because Java always passes a copy of the variable's value to methods. For primitives, this is the actual value, and for objects, it is a copy of the reference to the object. This topic is common to know for a Java developer, and it's often asked in most of the Java interview questions.
The memory storage area in JVM is a fundamental topic in Java that often comes up in Java interview questions.
Below are the various memory storage components of the JVM:
Understanding JVM memory areas is vital for every Java developer, and it's one of the most commonly asked in many of the Java interview questions.
Java’s ‘Write Once, Run Anywhere’ nature is commonly asked in Java interview questions. This is possible because of the Java Virtual Machine (JVM). When compiled, Java programs are converted into bytecode (a .class file) rather than directly into machine-specific code.
This bytecode can be executed on any system with a JVM, so the same compiled code can run on different machines without requiring recompilation for each hardware type. This is a key concept in Java, and it's often asked in most of the Java interview questions.
The Java ClassLoader is an abstract class in the java.lang package. It loads classes from various sources as needed, handling the loading process at runtime. This means that the JVM links classes dynamically, loading them only when required.
If a loaded class relies on another, the dependent class is also loaded. When a class is requested, the ClassLoader delegates this request to its parent to keep the runtime environment consistent. The ClassLoader is crucial for executing Java programs. This concept is important in Java, and it's often covered in most of the Java interview questions.
Below are the differences between JDK, JRE, and JVM:
Characteristic | JDK | JRE | JVM |
---|---|---|---|
Full Name | Java Development Kit | Java Runtime Environment | Java Virtual Machine |
Purpose | Development of Java applications. | Running Java applications. | Executing Java bytecode. |
Components | JRE + development tools (compiler, debugger, etc.). | JVM + libraries + other components. | Core component for executing Java code. |
Target Users | Java developers. | End-users of Java applications. | Part of both JDK and JRE. |
Feature | Provides tools to develop Java programs. | Provides a runtime environment to run Java programs. | Provides platform independence for Java. |
The declaration of the main function in Java as the public static void main(String args[]) is crucial as the execution starts from the main method. This is a common topic that often appears in most of the Java interview questions.
Here’s what each term signifies:
The Java program will run successfully if you use a static public void main instead of the conventional public static void main. Java is flexible with the order of access modifiers, so both declarations are valid for the main method. This concept is often highlighted in most of the Java interview questions.
This concept is often featured in most of the Java interview questions. The String pool is a storage area within the Java heap where string literals are stored.
This pool is also known as the String Intern Pool or String Constant Pool and is managed privately by the Java String class. When a string is created, it occupies space in heap memory, and creating multiple strings can increase memory usage, which affects performance.
To improve performance and reduce memory usage, the JVM optimizes string storage through the String pool. When a string literal is created, the JVM checks the pool to see if that literal already exists. If it does, the JVM returns a reference to the existing string. If it does not, a new String object is added to the pool.
In simple terms, a package in Java is a grouping of related classes, subclasses, enumerations, annotations, and interfaces. Each class in Java belongs to a particular package. To use a specific class, you must first import the corresponding package. Questions about packages are commonly asked in most of the Java interview questions as they are fundamental to Java's modularity.
Packages are used to:
Java has two main categories of data types:
Understanding these distinctions is important for fresher Java developers, and it's often asked in most of the Java interview questions.
Variables are used to store values, and each value is associated with a specific data type that determines the type of information it represents. These data types can be broadly classified into two main categories: Primitive data types and non-primitive data types.
The following table highlights the major differences between primitive and non-primitive data types:
Characteristic | Primitive Data Types | Non-primitive Data Types |
---|---|---|
Definition | Basic data types provided by Java. | Object references to instances of classes. |
Memory Allocation | Stored in stack memory. | Stored in heap memory. |
Default Value | Have default values (e.g., 0 for int). | The default value is null. |
Size | Fixed size depending on the data type. | Size can vary. |
Methods | Cannot have methods | Can have methods |
Passing to Functions | Passed by value | Passed by reference |
Examples | int, char, boolean, double, etc. | String, Array, Class, Interface, etc. |
A variable is a named area in memory reserved to store data. Essentially, it is the name of a memory location. The term combines "vary" and "able," meaning that the value stored in a variable can change.
Syntax:
dataType variableName = value; // Declaration with initialization
dataType variableName; // Declaration only
It is a fundamental concept in Java, and it’s frequently asked in most of the Java interview questions.
No, Java does not support pointers explicitly. This is primarily for:
This is a straightforward yet vital topic in Java, and it is often asked in most of the Java interview questions.
In Java, the default value of the byte datatype is 0. This is a common question in Java interview questions, especially when addressing primitive data types.
A Wrapper class in Java is a class that contains primitive data types within an object. When an object of a wrapper class is created, it includes a field where a primitive data type can be stored.
In other words, a primitive value is wrapped into an object of a wrapper class. The main wrapper classes are:
Wrapper Class | Primitive Type |
---|---|
Integer | int |
Double | double |
Boolean | boolean |
Character | char |
Float | float |
Long | long |
Short | short |
Byte | byte |
Wrapper classes are frequently asked in most of the Java interview questions due to their importance in object-oriented programming.
Wrapper classes are crucial in Java for several reasons:
This topic is often emphasized in many of the Java interview questions as it relates to Java's object-oriented features.
The table below shows the commonly used conventions for various identifiers.
Identifier Type | Naming Rules | Examples |
---|---|---|
Class | It should start with an uppercase letter. It should be a noun, like Student, Invoice, or Library. | public class Product |
Interface | It should start with an uppercase letter. It should be an adjective, like Comparable, EventListener. | interface Connectable |
Method | It should start with a lowercase letter. It should be a verb, like fetchData(), saveFile(). | void calculateSuml() |
Variable | It should start with a lowercase letter. It should not start with special characters like $, &, _. | int totalAmount; |
Package | All lowercase. If multiple words, it should be separated by dots, like java.lang. | package com.lambdatest; |
Constant | All uppercase letters. If multiple letters, it should be separated by underscores, like MAX_HEIGHT. | static final int DEFAULT_COUNT = 8; |
Java operators are symbols used to perform operations on variables, manipulating the values of the operands. Each operator has a specific purpose. Let us consider an expression 3 + 6 = 9; here, 3 and 6 are operands, and the symbol + (plus) is called the operator. Understanding operators is a basic foundation for Java developers, and it's often asked in most of the Java interview questions.
In Java, the = operator is right-associative. This means an assignment is evaluated from right to left. For example, in x = y = 10, y is assigned 10, and then x is assigned the value of y.
In Java, a class variable is a variable declared inside a class but outside any method, constructor, or block. Class variables use the static keyword and are shared by all instances (objects) of the class and by the class itself.
Regardless of how many objects are created from a class, each class variable has only one instance across them all. Class variables are frequently highlighted in many of the Java interview questions for their role in memory management.
Local variables in Java do not have default values, so they must be initialized before use. This applies to both primitive types and object references within a method, which remain unassigned until explicitly given a value.
In Java, a static method is associated with a class rather than any instance of the class. It can be accessed by all instances of the class, yet it is not tied to any specific object and can be called directly using the class name without creating an object.
Static methods exist independently of objects and can be invoked even if no object of the class has been created. Static methods are independent of objects and often featured in most of the Java interview questions for their utility in designing utility functions.
In Java, the equals() method and the == operator are used to compare two objects.
The equals() method compares two strings and returns true if all the characters in both strings match; otherwise, it returns false.
On the other hand, the == operator compares the references or memory locations of the objects in the heap. It checks whether the two references point to the same memory location.
Below are the key differences between the == operator and equals() method:
Characteristic | == Operator | equals() Method |
---|---|---|
Purpose | Compares object references. | Compares object content. |
Default behavior | Check if two references point to the same object in memory. | Checks if two objects are equal based on content (must be overridden in custom classes). |
Works with | Primitives and objects. | Objects only |
Null safety | It can be used with null values. | Throws NullPointerException if the object is null. |
Performance | Generally faster | It can be slower, depending on the implementation. |
Use case | Checking if two references point to the same object. | Comparing the content or logical equality of objects. |
This comparison has often been asked in most of the Java interview questions.
Static methods in Java have several restrictions:
Yes, all non-static methods in Java are virtual by default. This means their implementation is determined at runtime based on the object's actual type, enabling polymorphism.
Java has four types of access specifiers:
Static methods cannot be abstract because they are associated with the class, not with instances. Abstract methods require implementation in subclasses, but static methods cannot be overridden, making such a concept meaningless.
Below are the primary differences between String and StringBuilder:
Characteristics | String | StringBuilder |
---|---|---|
Mutability | Immutable | Mutable |
Thread Safety | Thread-safe | Not thread-safe |
Performance | Less efficient for frequent modifications | More efficient for frequent modifications. |
Memory Usage | It can be less efficient due to the creation of new objects. | More memory-efficient for multiple modifications. |
Concatenation | Uses + operator | Uses append() method. |
Use Case | When the string value doesn't change frequently. | When string value changes frequently. |
The covariant return type allows a method in a subclass to have a return type that is a subtype of the return type declared in the superclass.
Before Java 5, changing the return type was not allowed when overriding a method. However, since Java 5, it has become possible to override a method and change the return type to a subclass type, as long as the original return type is non-primitive.
Here’s a simple example:
class Parent {
Parent getValue() {
return this;
}
}
class Child extends Parent {
@Override
Child getValue() {
return this;
}
void display() {
System.out.println("This is covariant return example");
}
public static void main(String args[]) {
new Child().getValue().display();
}
}
In Java, serialization converts an object into a byte stream. This byte stream contains both the data of the instance and the type of that data.
Deserialization reverses this process, turning the byte sequence back into the original object. If we want to prevent a specific field from being serialized, we can use the transient keyword. This is the key concept in Java and is often highlighted in most of the Java interview questions.
StringBuffer is a fundamental topic in Java that highlights the concept of mutable strings and frequently appears in Java interview questions. The StringBuffer class in Java represents a mutable string of characters. It provides an alternative to the immutable String class, allowing you to modify a string's contents without creating new objects each time.
Mutable strings can be created using the StringBuffer class, which is similar to the String class, but it allows for changes. This concept is often discussed in most of the Java interview questions.
An array is a collection of elements of the same type stored in contiguous memory locations.
In Java, an array is an object that holds elements of a similar data type. The elements are stored in a contiguous block of memory, and it is a data structure that allows only a fixed number of elements.
Java arrays are index-based, meaning the first element is at index 0, the second element is at index 1, and so on. Java arrays are declared with square brackets, and the size is also indicated during the declaration.
Syntax:
int[] Arr = new int[9];
Below are some of the advantages of an array:
Below are some of the limitations of an array:
Arrays in Java are stored in heap memory. When an array is created using the new keyword, space is allocated in the heap for its elements. The Java Virtual Machine (JVM) manages this heap memory, which is shared among all threads in the Java program.
The JVM uses a garbage collector to reclaim memory that is no longer in use. Arrays in Java are created dynamically, meaning their size is determined during program runtime. The size of the array is specified when it is declared and cannot be changed after the array is created.
An object is a fundamental concept in Java and is often asked in most Java interview questions as it is an entity that possesses both state and behavior.
An object has three main characteristics:
A class is also a fundamental concept in Java and is often asked in most Java interview questions. A class is a collection of objects that share common properties. It is a template or blueprint for creating objects. A class is a logical entity and does not have a physical form.
In Java, a class can include:
The new operator is used to create objects in Java. However, if we need to determine the type of object to create at runtime, the new operator cannot be used. Instead, the newInstance() method can be used for this purpose.
In Java, this is a reference variable that refers to the current object.
There are five different ways to create an object in Java:
Object cloning in Java has several advantages and limitations, as mentioned below:
Advantages:
Limitations:
In Java, a constructor is a code block that functions like a method and is executed when an instance of a class is created. During this process, memory is allocated for the object. A constructor is used to initialize the object. Whenever an object is created using the new keyword, at least one constructor is invoked.
If no constructor is defined in the class, a default constructor is called, which the Java compiler provides automatically.
There are two types of constructors in Java:
Below are the differences between constructor and method in Java:
Characteristics | Constructor | Method |
---|---|---|
Purpose | Initializes object state and allocates memory. | Performs operations and implements behavior. |
Naming | It must have the same name as the class. | It can have any valid name. |
Return Type | No return type (not even void). | Must have a return type (void or any data type). |
Default Constructor | Provided by the compiler if not defined. | No default method is provided by the compiler. |
Inheritance | It cannot be inherited. | It can be inherited (unless declared private/static). |
Overriding | It cannot be overridden (can be overloaded). | It can be both overridden and overloaded. |
No, a constructor is not inherited. When a subclass extends a superclass, it inherits the superclass's state and behavior through variables and methods, but it does not inherit the superclass's constructor. This is because constructors have the same name as their class, so inheriting a parent class constructor in the child class would violate the rule that a constructor should match the class name.
Additionally, if constructors could be inherited, it would conflict with encapsulation principles, as it would allow access to private members of the superclass. Instead, super() is automatically added in the child class constructor if there’s no explicit call to super or this. Constructor is an important topic in Java, and it’s often covered in most of the Java interview questions.
A default constructor is used to initialize an object with default values, such as 0 or null, depending on its data type.
In Java, a copy constructor is a special constructor that creates a new object by copying the attributes of an existing object from the same class. It generates a duplicate of the original object.
Unlike the clone() method, which cannot assign values to final fields, the copy constructor can do so. Using a copy constructor is often simpler than implementing the clone() method, especially when creating a deep copy of an object. Copy constructors are an important topic in Java, and it’s often covered in most of the Java interview questions.
In Java, an interface acts as a blueprint for a class. It contains static constants and abstract methods.
In an interface, only abstract methods and variables are allowed without any method implementations. This setup represents an IS-A relationship, and, like abstract classes, interfaces cannot be instantiated. Interface is a crucial concept in Java, and it’s often covered in most of the Java interview questions.
A functional interface is an interface that contains exactly one abstract method. It can have any number of default and static methods but can only contain one abstract method. It can also declare methods from the Object class. Functional interfaces are also known as Single Abstract Method (SAM) interfaces and are a feature in Java that supports a functional programming approach.
No, the constructor does not return any value.
Data encapsulation is a crucial topic in Java, and it's often asked in most of the Java interview questions. Data encapsulation means bundling code and data together into a single unit, like a capsule that combines different medicines.
To create a fully encapsulated class in Java, all class data members are made private. Then, getter and setter methods are used to access and update the data. A Java Bean class is a good example of a fully encapsulated class.
This advantage of encapsulation is often asked in Java interview questions.
Here are some advantages of encapsulation in Java:
Inheritance in Java is a mechanism where one object inherits properties and behaviors from a parent object. It plays a significant role in Object-Oriented Programming (OOP).
The concept of inheritance means creating new classes based on existing ones. By inheriting from a parent class, methods and fields from that class can be reused. Additionally, new methods and fields can be added to the current class.
Inheritance represents an IS-A relationship, often described as a parent-child relationship.
Java supports the following four types of inheritance:
Example:
class TeamLead {
public void manageProject() {
System.out.println("The team lead is managing the project.");
}
}
class Developer extends TeamLead {
public void writeCode() {
System.out.println("The developer is writing code.");
}
}
public class Main {
public static void main(String[] args) {
Developer dev = new Developer();
dev.manageProject();
dev.writeCode();
}
}
Example:
class CTO {
public void setStrategicDirection() {
System.out.println("The CTO is setting the strategic direction.");
}
}
class SoftwareArchitect extends CTO {
public void designSystem() {
System.out.println("The software architect is designing the system.");
}
}
class Developer extends SoftwareArchitect {
public void writeCode() {
System.out.println("The developer is writing code.");
}
}
public class Main {
public static void main(String[] args) {
Developer dev = new Developer();
dev.setStrategicDirection();
dev.designSystem();
dev.writeCode();
}
}
Example:
class Developer {
public void writeCode() {
System.out.println("The developer is writing code.");
}
}
class FrontendDeveloper extends Developer {
public void buildUI() {
System.out.println("The frontend developer is building the user interface.");
}
}
class BackendDeveloper extends Developer {
public void implementAPI() {
System.out.println("The backend developer is implementing the API.");
}
}
class FullStackDeveloper extends Developer {
public void handleEndToEnd() {
System.out.println("The full-stack developer is handling the end-to-end development.");
}
}
public class Main {
public static void main(String[] args) {
FrontendDeveloper frontend = new FrontendDeveloper();
frontend.writeCode();
frontend.buildUI();
BackendDeveloper backend = new BackendDeveloper();
backend.writeCode();
backend.implementAPI();
FullStackDeveloper fullstack = new FullStackDeveloper();
fullstack.writeCode();
fullstack.handleEndToEnd();
}
}
Example:
abstract class Application {
public void launch() {
System.out.println("The application is launching.");
}
}
interface Mobile {
void runOnMobile();
}
interface Web {
void runOnWeb();
}
class FullStackDeveloper extends Application implements Mobile, Web {
public void runOnMobile() {
System.out.println("The application is running on a mobile device.");
}
public void runOnWeb() {
System.out.println("The application is running on the web.");
}
}
public class Main {
public static void main(String[] args) {
FullStackDeveloper fullstack = new FullStackDeveloper();
fullstack.launch();
fullstack.runOnMobile();
fullstack.runOnWeb();
}
}
Inheritance is a core concept in Java, as it enhances flexibility and is a key feature of Object-Oriented Programming (OOP). Understanding this concept is crucial, and it is often emphasized in many Java interview questions.
Java does not support multiple inheritance, meaning a class cannot inherit from more than one parent class. Multiple inheritance can create ambiguity when methods in parent classes share the same signature, making it difficult for the compiler to determine which method should be used.
The Object class is the superclass of every class in Java. All classes, directly or indirectly, inherit from the Object class.
Understanding how inheritance in C++ is different from inheritance in Java is important, and it is often asked in most Java interview questions.
Java’s inheritance model differs from C++ in several ways. While both support inheritance, in Java, all classes inherit from the Object class, forming a single inheritance tree. Java uses the extends keyword for inheritance and does not use access specifiers (like public, protected, or private) to modify the inheritance relationship. In contrast, C++ allows more flexibility with these specifiers.
Additionally, Java’s methods are virtual by default, unlike C++, where the virtual keyword is needed. Java also does not support multiple inheritance but allows a class to implement multiple interfaces, whereas C++ allows multiple inheritance directly. Java uses the super keyword to invoke parent class constructors and methods.
The final keyword in Java is used to prevent a method from being overridden. By default, methods in Java are virtual, which means they can be overridden. When declared final, a method cannot be changed or overridden in any subclass. This is one of the most commonly asked questions in most of the Java interview questions.
Aggregation is a "HAS-A" relationship between two classes, where one class contains an entity reference to another. For example, a Project class can have a collection of Developer objects, representing a "HAS-A" relationship between the Project and Developer classes.
class Project {
int projectId;
String projectName;
LocalDate deadline;
List<Developer> developers; // Developer is a class
String status;
...
}
Composition is a design approach that represents a "has-a" relationship, while inheritance represents an "is-a" relationship. This is one of the key concepts in Java, and it’s often appeared in many of the Java interview questions.
Both composition and inheritance support reusable code in a program. In composition, a class holds an instance variable that points to another object, creating a dependent relationship.
This type of relationship occurs when one object includes another and depends on it to function. If the main object is removed, the contained object no longer serves any purpose. In simple terms, composition is a method for describing how two or more classes relate to one another. The instance variable in composition should be initialized before it is used to establish this link between classes.
Aggregation and composition are both types of association in object-oriented programming that describe the relationship between two classes.
Below is a table comparing the primary differences between aggregation and composition:
Characteristics | Aggregation | Composition |
---|---|---|
Relationship Type | "Has-A" (weak relationship) | "Part-Of" (strong relationship) |
Lifecycle Dependency | Parts can exist independently. | Parts cannot exist without the whole. |
Ownership | The child can belong to multiple parents. | The child belongs to only one parent. |
Dependency Level | Loose coupling | Tight coupling |
Object Creation/Deletion | Child objects can survive if the parent is deleted. | Child objects are deleted when the parent is deleted. |
Data Sharing | Objects can be shared. | Objects cannot be shared. |
Association is a key concept in object-oriented programming that shows how two independent classes relate to each other. It represents a “uses-a” relationship, where one object interacts with another. This interaction can occur in several ways, such as one-to-one, one-to-many, many-to-one, or many-to-many.
Types of Association:
In Java, the super keyword is used to refer to the immediate parent class object.
It allows access to parent class constructors, methods, and variables.
No, you cannot use both this() and super() in a single constructor. If used, one must be called first.
Polymorphism is a primary feature in Object-Oriented Programming and frequently appears in Java interview questions. It lets a single action be performed in multiple ways. This is one of the most commonly asked questions in many of the Java interview questions.
This approach provides a single interface that can have various implementations. The term combines “poly,” meaning many, and “morph,” meaning forms, which means multiple forms.
Java supports two types of polymorphism:
Polymorphism can be achieved through method overloading and method overriding. This is one of the most commonly asked questions in many of the Java interview questions.
In Java, overriding allows a child class to define its version of a method that exists in its parent class. If a method in a subclass has the same name, parameters, and return type (or subtype) as a method in its superclass, then the subclass method overrides the parent method. Method overriding is a way to achieve runtime polymorphism in Java.
In Java, method overloading allows multiple methods in the same class to share the same name but differ in their parameter lists. This can involve having a different number of parameters, types of parameters, or a combination of both.
This approach is also called compile-time polymorphism, static polymorphism, or early binding because the method to be executed is determined during compilation.
Yes, overloaded methods can be overridden in Java.
Yes, we can overload the main() method in Java. A class can contain multiple versions of main() with different parameter lists. However, the Java Virtual Machine (JVM) looks specifically for the standard main() method signature, public static void main(String[] args), to start execution.
Without this exact version, the program will compile successfully but will not run, as the JVM requires this original main() method to launch the application.
Whether a Java program can be executed without the main() method depends on the version of Java. Before JDK 7, the main method was not mandatory. A program could be executed by placing the code inside a static block, which runs when the class is loaded before the main() method is called.
From JDK 7 onwards, the main method became mandatory. The compiler checks for its presence, and if it is missing, an error stating "main method not found in the class" will occur. This error is a bytecode verification error, as the program has not yet been executed.
No, we cannot override private methods in Java. Since private methods are only accessible within the class where they are defined, they are not visible to subclasses, which prevents them from being overridden.
Static methods are also not eligible for overriding, as they belong to the class itself rather than an instance, so they do not participate in inheritance in the same way as instance methods.
In Java, abstraction is a method of hiding unnecessary details and only displaying essential functionality to the user. This concept helps focus on what an object does rather than how it does it. This is the core concept in Java, and it’s often covered in many of the Java interview questions.
Abstraction is achieved through interfaces and abstract classes. Using interfaces, we can implement complete abstraction and hide all implementation details.
Abstraction and Encapsulation are two core concepts in Object-Oriented Programming. Understanding the differences between these concepts is essential, as they are frequently discussed in Java interview questions.
Characteristics | Abstraction | Encapsulation |
---|---|---|
Definition | Hiding complex implementation details and showing only functionality to the user. | Bundling data and methods that operate on that data within a single unit/class. |
Purpose | Manages complexity by hiding unnecessary details. | It prevents direct access to data and preserves data integrity. |
Focus | What an object does. | How an object does it. |
Level | It occurs at the design level. | It occurs at the implementation level. |
Implementation | Using abstract classes and interfaces. | Using access modifiers (public, private, protected). |
In Java, an abstract class cannot create objects on its own. Instead, it must be extended by another class to make use of its properties and methods. The abstract keyword is used to define an abstract class that contains methods or properties meant to be shared with subclasses but not used directly.
The Java interview questions discussed above are fundamental and essential for any fresher to understand, as they form the foundation for mastering Java programming concepts and practices. Developing a strong grasp of these basics is vital for building a solid skill set and excelling in interviews.
As you progress, you will encounter intermediate-level Java interview questions that dive deeper into the language's features and applications. Tackling these will expand your knowledge, enhance your problem-solving skills, and prepare you to handle more complex challenges, ultimately advancing your expertise in Java programming.
This section covers Java interview questions for intermediate-level candidates who have a good grasp of the basics and some programming experience. These questions explore more complex topics like collections, exception handling, multithreading, and serialization.
A variable declared as final in Java cannot have its value modified after it is initially set. This makes it useful for defining constants or values that must remain unchanged throughout the program. Understanding the concept of final variables is essential for Java developers, and it's often covered in many of the Java interview questions.
There are two main ways to synchronize an ArrayList in Java, a common topic in Java interview questions:
List<String> list = Collections.synchronizedList(new ArrayList<String>());
List<String> list = new CopyOnWriteArrayList<String>();
Arrays store primitive data types in contiguous memory locations, while ArrayLists store object references instead of the actual primitive values. This is because arrays can directly store primitive data, occupying sequential memory addresses.
On the other hand, ArrayLists manage an internal array that holds references to objects rather than the primitive values themselves. As a result, the memory layout of an ArrayLists is not contiguous like an array since the objects are stored at various locations in memory.
This distinction is important to know for any Java developer, and it often appears in most of the Java interview questions.
The size of an ArrayList grows dynamically to make space for more elements. When you first create an ArrayList, it usually has a default capacity of about 10 to 16 elements. This number can change depending on the version of Java you are using.
When the current array becomes full, and you try to add more elements, the ArrayList needs to increase its size. It creates a new array that is larger than the old one. The new array is often about one and a half times the size of the old array.
After creating the new array, the ArrayList copies all the elements from the old array to the new array. Once this copying is complete, the ArrayList updates its internal reference to point to the new array. This process of making an array bigger is called resizing.
Default methods are methods in an interface that can have a body. These methods allow interfaces to provide default implementations of some methods, making them more flexible. This is a crucial concept for Java interview questions related to the evolution of Java interfaces in Java 8 and beyond.
Yes, even with a garbage collector, a program can still run out of memory. Garbage collection helps identify and remove objects that are no longer needed. This process frees up resources used by these objects.
When an object becomes unreachable in a program, garbage collection is triggered for that object. If there is not enough memory to create new objects, the garbage collector works to free memory from objects that are no longer in scope. However, if the amount of memory released is not enough to create new objects, the program can exceed its memory limit. Garbage collection is the core aspect of Java, and it’s often mentioned in most of the Java interview questions.
In object-oriented programming (OOP), both abstract classes and interfaces are essential constructs for creating contracts that define specific behaviors for implementing classes. Understanding the differences between these two is important, as they are commonly discussed topics in Java interview questions.
Below are the detailed differences between abstract classes and interfaces:
Characteristics | Abstract Class | Interface |
---|---|---|
Definition | A class that is partially implemented. | A contract that defines a set of abstract behaviors. |
Variables | It can have instance variables, static variables, and constants. | It can only have constants (public static final). |
Constructor | It can have constructors. | It cannot have constructors. |
Multiple Inheritance | It cannot support multiple inheritance. | It can implement multiple interfaces. |
Extension | extends keyword | implements keyword |
Usage Scenario | When you want to share code among related classes. | When you want to define a contract for behavior. |
Collections in Java refer to groups of objects. The collection framework is a set of interfaces and classes that represent and manage these groups of objects in different ways. It includes classes like ArrayList, Vector, LinkedList, PriorityQueue, and TreeSet.
Additionally, the framework provides multiple interfaces, including Set, List, Queue, and Deque. Each interface is designed to store a specific type of data.
In Java, you can create a read-only view of an ArrayList by using the Collections.unmodifiableList() method.
This method takes an existing ArrayList as input and returns an unmodifiable view of that list.
Here's an example:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class UnmodifiableArrayList {
public static void main(String[] args) {
List<String> languageList = new ArrayList<>();
languageList.add("Java");
languageList.add("Python");
languageList.add("C++");
languageList.add("C#");
List<String> readOnlyList = Collections.unmodifiableList(languageList);
readOnlyList.add("JavaScript");
languageList.add("JavaScript");
System.out.println(languageList); // [Java, Python, C++, C#, JavaScript]
}
}
In this example, we first create a regular ArrayList called languageList and add some programming languages to it. Then, we use the Collections.unmodifiableList() method to create a read-only view of the languageList called readOnlyList.
The Stack Class in Java is a data structure that follows the Last-In-First-Out (LIFO) principle. It extends the Vector class and provides specific methods for stack operations. In a stack, elements are added and removed from the top, similar to a stack of plates where you can only add or remove plates from the top.
The various methods provided by the Stack class are:
The HashSet class in Java is part of the collections framework, which is inherited from the AbstractSet class and implemented in the Set interface. It uses a hashtable, which is a HashMap, to store a collection of unique elements.
The hashtable uses a process called hashing to store information. Hashing converts information into a unique value, or "hash code," which helps locate data linked to a key. This transformation from information to hash code happens automatically within the HashSet.
The Map interface in Java is a structure that contains a set of key-value pairs, where each key is unique and corresponds to a single value. It is part of the java.util package and is commonly used in Java programming to organize and retrieve data in an ordered fashion, and it’s often asked in most of the Java interview questions. A Map is particularly helpful for searching, updating, or deleting elements based on a key.
To create an immutable class in Java, follow these steps:
The TreeMap in Java is an implementation of the Map interface, NavigableMap, and AbstractMap class. Depending on the constructor used, it sorts the map according to the natural ordering of its keys or by a Comparator provided during the map's creation.
Features of a TreeMap:
The EnumSet is a specialized form of the Set interface for use with enumeration types.
Some features of EnumSet include:
A BlockingQueue is a type of queue that has operations for handling cases when the queue is empty or full. It will wait until there is something in the queue if we try to retrieve an item from an empty queue, and it will wait for space to free up if we try to add an item to a full queue.
Some important points about BlockingQueue:
ConcurrentHashMap in Java is a class that implements the ConcurrentMap and Serializable interfaces. This class builds on the HashMap to work efficiently in multithreaded environments. ConcurrentHashMap provides improved performance over HashMap in these cases, as it handles concurrent updates and retrievals without the need for synchronization on the whole map, making it more suitable and effective for multithreaded tasks.
In Java, an Iterator is a type of cursor used to loop through a collection of objects one at a time. It is an interface found in the java.util package that provides access to elements in a collection.
The Iterator is often referred to as Java’s universal cursor since it works with any class in the Collection framework. It supports actions like reading and removing items from the collection. Compared to the older Enumeration interface, Iterator provides methods with simpler and clearer names, making it easier to use.
An enumeration (enum) in Java is a unique data type that includes a fixed set of predefined constants.
A common topic that often appears in Java interview questions is the difference between collection and collections in Java.
Here's a concise comparison:
Characteristics | Collection | Collections |
---|---|---|
Type | Interface | Utility class |
Purpose | Represents a group of objects. | Provides static methods for Collection objects. |
Usage | Used to create collection objects. | Used to manipulate or query collection objects. |
Instantiation | It can be instantiated via implementations (e.g., ArrayList). | It cannot be instantiated (all methods are static). |
Examples | List, Set, Queue | sort(), binarySearch(), reverse() |
In Java, an iterator is used to traverse a collection's objects.
Collections provide two types of iterators: Fail Fast and Fail Safe.
Fail Fast Iterator: Fail Fast iterators immediately throw a ConcurrentModificationException if the collection undergoes structural changes during iteration. Structural changes include adding, removing, or updating elements while another thread is iterating over the collection. Examples of Fail Fast iterators include those from ArrayList and HashMap.
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class FailFastExample {
public static void main(String[] args) {
Map<String, String> cityMap = new HashMap<String, String>();
cityMap.put("Harry", "London");
cityMap.put("Ron", "Paris");
cityMap.put("Hermione", "Tokyo");
Iterator iterator = cityMap.keySet().iterator();
while (iterator.hasNext()) {
System.out.println(cityMap.get(iterator.next()));
cityMap.put("Brown", "Sydney");
}
}
}
Fail Safe Iterator: Fail Safe iterators work differently from Fail Fast iterators. They do not throw exceptions when the collection is modified during iteration. This is because they work on a copy of the collection instead of the original. Any structural changes made to the original collection do not affect the copy, so the original collection remains unchanged during iteration.
Although the term "Fail Safe" is not explicitly used in Java SE documentation, it is often referred to as a non-Fail Fast iterator.
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.Iterator;
class FailSafeExample {
public static void main(String args[]) {
CopyOnWriteArrayList<Integer> numbers
= new CopyOnWriteArrayList<Integer>(new Integer[] { 5, 10, 15, 20 });
Iterator itr = numbers.iterator();
while (itr.hasNext()) {
Integer value = (Integer)itr.next();
System.out.println(value);
if (value == 10) {
numbers.add(25);
}
}
}
}
Exception handling is a method for managing runtime errors that may occur in a program. Examples of such errors include ClassNotFoundException , IOException, SQLException, and RemoteException. This mechanism helps maintain the normal flow of the application by allowing the program to respond appropriately when an error occurs.
In Java, there are two main types of exceptions:
Built-in Exceptions: These are exceptions provided by Java libraries to represent specific error situations.
Here are some important built-in exceptions:
User-Defined Exceptions: In some cases, built-in exceptions may not effectively describe a specific situation. In these instances, users can create their exceptions, known as user-defined exceptions.
A NullPointerException (NPE) is one of Java's most common runtime exceptions. It occurs when code attempts to operate on a null object reference.
This happens in scenarios like:
An ArrayStoreException in Java happens when there is an attempt to store an object of an incorrect type in an array.
This exception extends the RuntimeException class, which means it occurs during the execution of a program. This is the most commonly occurred expectation in Java and is often asked in many of the Java interview questions.
The base class for both Error and Exception in Java is the Throwable class.
No, it is not necessary to follow every try block with a catch block in Java. You can use a finally block instead, which runs regardless of whether an exception is thrown.
When an exception occurs in Java, it starts from the top of the call stack. If the exception is not caught in that method, it moves down to the previous method in the stack. This process continues until the exception is caught or it reaches the bottom of the call stack. This process is known as exception propagation.
Object cloning in Java is a technique used to create an exact copy of an object. The clone() method from the Object class is responsible for cloning an object.
To enable cloning, a class must implement the java.lang.Cloneable interface. If the class does not implement this interface, invoking the clone() method will result in a CloneNotSupportedException.
The clone() method is defined in the Object class and is used to perform the cloning operation. Below is the syntax of the clone() method:
protected Object clone() throws CloneNotSupportedException
Below are the differences between this() and super() in Java:
Characteristics | this() | super() |
---|---|---|
Purpose | Calls another constructor in the same class. | Calls a constructor in the immediate parent class. |
Inheritance | Used within the same class. | Used to access parent class members. |
Default call | If not explicitly called, the compiler doesn't insert it. | If not explicitly called, the compiler inserts super(). |
Scope | Refers to the current instance of the class. | Refers to the parent class instance. |
Multitasking means a system can run several tasks at the same time or during overlapping periods. There are two main ways to achieve this: using multiple processes or using multiple threads. In Java, the focus is mainly on multitasking with threads.
Multithreading in Java is a method for executing multiple threads simultaneously. A thread acts as a lightweight sub-process, representing the smallest unit of processing. Both multiprocessing and multithreading achieve multitasking.
However, multithreading is preferred over multiprocessing because threads share a memory area. This means threads do not need separate memory space, which saves memory. Additionally, switching between threads requires less time than switching between processes. Multiprocessing and multithreading are core concepts in Java, and it’s often asked in many of the Java interview questions.
Advantages of Java Multithreading:
There are two ways to create a thread in Java:
By Extending the Thread Class: You can create a class that extends the java.lang.Thread class. In this class, you need to override the run() method, which contains the code for the thread. The thread starts executing when the run() method is called.
Syntax:
public class MyThread extends Thread {
public void run() {
// thread code }
}
By Implementing the Runnable Interface: In this approach, you create a new class that implements the java.lang.Runnable interface. You must override the run() method in this class. After creating an instance of your Runnable class, you create a Thread object and call the start() method on it to begin execution.
Syntax:
public class MyRunnable implements Runnable {
public void run() {
// thread code
}
}
A thread is a lightweight process and represents the smallest unit of a program that can run tasks simultaneously. It helps a program function more efficiently by allowing multiple operations to occur at the same time. Threads are one of the important concepts in Java and it has often been covered in most of the Java interview questions.
In Java, the thread concept is used to perform complex tasks in the background. These tasks execute without interrupting the main program. Each thread in a program has its separate execution path, making every thread independent within the process.
In Java, a thread can exist in one of the following states:
To temporarily suspend a thread in Java, the thread must be in the suspended state, which means it is inactive. The suspend() method is used for this purpose, allowing the thread to remain suspended until it is resumed by the resume() method.
The syntax for the suspend() method is as follows:
public final void suspend()
This method is final, meaning it cannot be overridden by subclasses. It has a void return type that does not return a value. The suspend() method temporarily stops the thread until the resume() method is called.
A daemon thread in Java acts as a service provider thread that supports user threads. Its lifecycle depends on user threads. When all user threads finish execution, the Java Virtual Machine (JVM) automatically terminates the daemon thread.
Several daemon threads run automatically in Java, such as the garbage collector and finalizer threads.
A thread can enter the waiting state in several ways. It may be called the sleep() method to pause for a specified duration. It can also become blocked while trying to acquire an object's lock or by calling the wait() method on an object. Additionally, a thread can enter the waiting state by using the suspend() method, although this method is deprecated.
Serialization in Java is the process of converting the state of an object into a byte stream. This is one of the core concepts in Java programming language and is often highlighted in most of the Java interview questions.
This byte stream represents the object's data and makes it possible to store or transmit the object. Java I/O (Input/Output) streams are used for this purpose, where a byte stream reads and writes one byte of data at a time, making it suitable for low-level data operations.
To make a class serializable in Java, the class must implement the Serializable interface.
Yes, a serialized object can be transferred over a network in Java.
The main difference between static and non-static methods is that static methods can be called without creating an instance of the class, while non-static methods can directly access any static method or static variable without needing to create an instance of the class.
Characteristics | Static Method | Non-Static Method (Instance Method) |
---|---|---|
Keyword | Declared using static keyword. | No special keyword is needed. |
Memory Efficiency | More memory efficient (single copy). | Each instance has its own copy. |
Common Use Case | Math.sqrt(), Arrays.sort() | Object.toString(), ArrayList.add() |
Syntax | static void method(){} | void method(){} |
Deserialization refers to converting a byte stream back into an object. It is the reverse operation of serialization, which transforms an object's state into a byte stream for storage or transmission. During deserialization, the byte stream is read and reconstructed into the original object, allowing access to its data and methods.
In Java, the ObjectInputStream class is commonly used for deserialization. It reads the byte stream and recreates the object based on its serialized state. This process is essential for restoring object states after transmission or storage, supporting data exchange and persistence across various platforms.
Reflection refers to the examination or modification of a class's runtime behavior. The java.lang.Class class provides methods to obtain metadata and alter the runtime behavior of a class. The java.lang and java.lang.reflect packages contain classes relevant to Java reflection.
In Java, the java.lang.Class class is a built-in class used to represent a class or interface during runtime. This class includes various methods that provide details about the class or interface. It provides information such as the name of the class, its superclass, implemented interfaces, fields, and methods.
There are three ways to create an instance of the Class class in Java:
The javap tool provides information about a class or interface. Often referred to as the Java Disassembler, it disassembles one or more class files. The output varies based on the options used, such as -c for bytecode or -verbose for detailed bytecode information. If no options are specified, javap displays the package, protected, and public fields and methods of the specified classes.
Syntax:
javap [option] [classname]
The native keyword in Java is used to declare a method that is implemented in native code through the Java Native Interface (JNI). This modifier is exclusive to methods and cannot be applied elsewhere. Methods written in languages like C . or C++ are referred to as native methods or foreign methods.
Autoboxing refers to converting a primitive value into an object of the corresponding wrapper class. For example, converting an int to an Integer class.
The Java compiler performs autoboxing in the following situations:
Unboxing refers to converting an object of a wrapper type back into its corresponding primitive value. For example, converting an Integer to an int.
The Java compiler applies unboxing in these scenarios:
In Java, the strictfp modifier stands for strict floating-point. It is used to restrict floating-point calculations, ensuring consistent results across different platforms during operations involving floating-point variables.
The System class is part of the java.lang package and cannot be instantiated. Its purpose is to provide standard output and error output streams, handle standard input, and grant access to externally defined properties and environment variables. Additionally, it provides a utility method for efficiently copying portions of an array and a means for loading files and libraries.
The BorderLayout is the default layout for the Window, Frame, and Dialog class containers in Java.
The FlowLayout is the default layout for the Panel and Applet classes in Java.
Lightweight components do not make native calls to acquire graphical units. Instead, they use the graphical units of their parent component for rendering.
Heavyweight components are the portable elements provided by the operating system. AWT relies on the graphical classes offered by the operating system, implementing only a minimal subset of screen elements supported across all platforms.
The user interface discovery tools dependent on the operating system are classified as heavyweight components.
An applet is a Java program that can be embedded directly into a web page. It runs within a web browser, operating on the client side to add interactive elements to websites.
Applets are embedded into HTML pages using the APPLET or OBJECT tags and are hosted on a web server. They provide a means of making web content more engaging and dynamic.
Some key points about applets:
In Java, an applet’s life cycle describes the sequence of steps an applet undergoes during its creation, execution, and termination.
The life cycle consists of five primary methods that the browser invokes during different phases of the applet’s life:
When an applet is first loaded, the sequence begins with init(), followed by start(), and then paint(). When the applet is stopped, stop() and destroy() are called in order to conclude its life cycle. This is one of the most important topics in Java programming language and is often asked in most of the Java interview questions.
Java applications and Java applets are both Java programs, but they differ in some aspects. A Java application always begins execution with the main() method. On the other hand, an applet initializes through the init() method without invoking the main() method.
This functions as stand-alone programs that run directly on the underlying operating system with the help of the Java Virtual Machine (JVM). They perform a variety of operations for users and do not rely on APIs or web browsers. Conversely, applets are small programs embedded in web pages. They use the OBJECT or APPLET tag for embedding in HTML pages and are hosted on web servers.
Java socket programming provides a way for communication between two machines using TCP. A client application creates a socket to connect to a server. When a connection occurs, the server produces a socket object to handle the interaction.
The java.net.Socket class represents the client socket, while the java.net.ServerSocket class listens for client connections.
Here are the steps for establishing a TCP connection:
Once connected, data can be exchanged through I/O streams. Each socket has an OutputStream and an InputStream. The client's OutputStream connects to the server's InputStream, while the server's OutputStream connects to the client's InputStream.
A socket is an endpoint for communication between machines. It provides the connection mechanism to link two computers using TCP. The Socket class can be utilized to create a socket.
RMI stands for Remote Method Invocation. It is an API that allows one object to invoke a method on another object residing in a different address space. This can occur on the same machine or a remote machine. RMI provides a way for an object running in one Java Virtual Machine (JVM) to call methods on an object in another JVM.
A servlet is a class in the Java programming language that increases the functions of servers that support applications based on the request-response programming model. Although servlets are capable of responding to any type of request, they are often used to extend the features of applications hosted on web servers. Java Servlet technology provides HTTP-specific servlet classes to support these types of applications.
In Java, Applets and Servlets are both types of programs that run within a Java environment. Applets are created to provide interactive features that can be embedded into web pages, enabling users to interact with content directly within their web browsers.
On the other hand, Servlets function on the server side, where they manage requests and responses, playing a crucial role in generating dynamic content for web applications.
Reusability is a fundamental focus in any programming language. To address this need, Java introduced the concept of JavaBeans. A JavaBean is a software component that can be reused across different environments.
Simply put, JavaBeans are classes that consolidate multiple objects into a single entity, making it possible to access these objects from various locations within an application. JavaBeans contain several key elements, including constructors, getter and setter methods, and additional components that support reusability and flexibility in development.
The persistence property of a JavaBean refers to its ability to save and restore the values of its properties, fields, and state information.
When a caller invokes a method on the stub object, the stub performs the following tasks:
When the skeleton receives a request, it performs the following tasks:
Writing RMI-based programs involves six steps:
The purpose of the volatile keyword in Java is to make sure that changes to a variable are visible to all threads. When a variable is declared as volatile, any thread that reads the variable will see the most recent value written to it. This helps prevent data inconsistencies when multiple threads are accessing and modifying the same variable. This keyword is important for Java developers to know, and it’s often highlighted in most Java interview questions.
The intermediate-level Java interview questions listed above are designed to help both beginners and those with some experience prepare effectively for interviews. As you progress in your Java development career, you will encounter more challenging questions that are particularly relevant for experienced developers. These questions will help you deepen your understanding and expertise in various Java concepts and technologies, ensuring you're well-prepared for more advanced roles.
This section is for experienced Java developers and includes Java interview questions on advanced topics. These questions cover some advanced topics and practical coding questions that test your problem-solving skills.
Garbage collection in Java is the process of reclaiming memory by removing objects that are no longer needed in a program. Unlike languages such as C and C++, where the programmer manually manages memory by creating and deleting objects, Java handles this automatically through garbage collection.
In Java, memory management occurs as objects are created on the heap during the program's runtime. Some of these objects become unused over time, either because they’re no longer referenced or they’ve outlived their purpose. The Java garbage collector identifies these dead objects that are no longer needed and removes them from memory, freeing up space for new objects.
This automated approach to memory management helps prevent memory leaks, which can occur when unneeded objects remain in memory. Eventually, this leads to program crashes with "OutOfMemoryErrors." By handling memory cleanup automatically, Java reduces the risk of memory-related errors, supporting a smoother runtime experience.
The finalize() method in Java helps clean up before an object is removed from memory. When the garbage collector is about to delete an object, it calls finalize() to release any resources the object is holding, which helps keep memory use efficient.
In Java, a memory leak occurs when the garbage collector fails to identify and reclaim unused objects. These objects remain in memory indefinitely, which reduces the available memory for the application. As a result, the application may encounter an OutOfMemoryError because the unused objects are still referenced.
To prevent memory leaks in Java, consider these important points:
Do not create objects that are not needed, as they consume memory.
Spring is an open-source framework for enterprise Java development. It offers core features applicable to any Java application and provides extensions for creating web applications within the Java EE platform. The Spring framework aims to simplify J2EE development and encourages good programming practices through a POJO-based (Plain Old Java Object) programming model.
Both System.gc() and Runtime.gc() methods in Java are used to request garbage collection. Garbage collection is the process where the Java Virtual Machine (JVM) reclaims memory from objects that are no longer reachable or needed, freeing up resources.
Key Points:
Common Behavior:
Example:
public class GarbageCollectionExample {
public static void main(String[] args) {
// Suggesting garbage collection using System.gc()
System.gc();
// Suggesting garbage collection using Runtime.gc()
Runtime.getRuntime().gc();
}
}
In Spring, the objects that are the backbone of your application and managed by the Spring IoC container are known as beans. A bean is an object that the Spring IoC container instantiates, assembles, and manages. These beans are created based on the configuration metadata you provide to the container.
Spring beans do not guarantee thread safety by default because their default scope is singleton. This means there is only one instance of the bean per context. Multiple threads accessing class-level variables that can be modified can lead to inconsistent data.
To achieve thread safety, changing the scope of a Spring bean to request, prototype, or session can be useful. Each of these scopes creates a new instance of the bean for each request or session. This reduces the risk of data inconsistency. However, this approach may impact performance.
Double Brace Initialization in Java refers to the combination of two processes. As the name suggests, this technique uses two sets of braces {{.
A single brace { is familiar to most programmers. The first brace in double brace initialization creates an anonymous inner class. This approach is common in Java programming. The second brace distinguishes this technique from standard brace usage in Java.
This second brace is an initialization block for the declared anonymous inner class. When used together, this initialization block and the anonymous inner class constitute what is known as Java double brace initialization.
Here are some drawbacks of garbage collection:
The java.util.regex package contains classes including Pattern, Matcher, and PatternSyntaxException.
JDBC stands for Java Database Connectivity. It is a Java API that is used to connect and execute queries with a database. JDBC requires specific JDBC drivers to connect to various database systems. This API can access tabular data stored in any relational database.
A JDBC driver is a software component that allows a Java application to communicate with a database.
There are four main types of JDBC drivers:
Java testing frameworks consist of a set of rules designed to support the creation and execution of test scripts. These frameworks provide guidelines for coding standards, handling test data, managing object repositories, and offering libraries.
Here are some widely used Java testing frameworks:
While Java testing frameworks like Selenium, JUnit, Cucumber, and Spring provide robust tools for creating and executing test scripts, managing diverse test environments and ensuring cross-browser and cross-platform compatibility can be challenging. This is where cloud-based platforms come into play.
Cloud-based testing platforms, like LambdaTest, integrate seamlessly with popular Java testing frameworks. They offer access to a wide range of browsers, devices, and operating systems, enabling teams to perform parallel testing at scale. LambdaTest is an AI-powered platform for test orchestration and execution that allows you to run manual and automated Java tests at scale across 3000+ browsers and OS combinations.
These platforms eliminate the need for maintaining physical infrastructure, reducing costs and setup time while ensuring comprehensive test coverage.
Additionally, cloud platforms provide advanced features like real-time debugging, CI/CD integration, and secure collaboration among teams, making them an ideal choice for modern testing needs. By leveraging cloud-based solutions you can use various frameworks simultaneously such as Selenium Java, Selenium Python and more, organizations can accelerate their testing cycles, improve efficiency, and deliver high-quality software faster.
The DriverManager class functions as an interface between the user and database drivers. It manages the available drivers and establishes connections between a database and the selected driver. This class maintains a list of driver classes that have registered themselves by calling the method DriverManager.registerDriver().
Unchecked exceptions are runtime exceptions that do not need to be caught or declared in a throws clause. They usually occur due to programming errors, such as accessing an invalid index in an array or dividing by zero.
On the other hand, unchecked exceptions include all subclasses of the RuntimeException class, as well as the Error class and its subclasses.
This program checks if a given number is prime. A prime number is only divisible by 1 and itself, meaning it has no other divisors. In this example, we iterate through an array of numbers 1, 23, 4, and 31, checking each one to see if it meets the criteria of a prime number and printing the result accordingly.
public class PrimeNumbers {
public static void main(String[] args) {
int[] numbersToCheck = {1, 23, 4, 31};
for (int number : numbersToCheck) {
boolean isPrime = isPrime(number);
if (isPrime) {
System.out.println(number + " is a prime number.");
} else {
System.out.println(number + " is not a prime number.");
}
}
}
public static boolean isPrime(int num) {
if (num <= 1) {
return false;
}
if (num == 2) {
return true; }
if (num % 2 == 0) {
return false; }
for (int i = 3; i <= Math.sqrt(num); i += 2) {
if (num % i == 0) {
return false;
}
}
return true;
}
}
This program swaps two numbers without using a third variable. Instead of an additional variable, it uses the XOR bitwise operator to exchange values directly. In this example, we start with the numbers 14 and 24, then apply three XOR operations to swap their values.
public class SwapNumbers{
public static void main(String[] args) {
int a = 14;
int b = 24;
System.out.println("Before swapping: a = " + a + ", b = " + b);
// Swapping using XOR
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println("After swapping: a = " + a + ", b = " + b);
}
}
This program checks if two strings are anagrams of each other. Anagrams are words or phrases formed by rearranging the letters of another, using all the original letters exactly once. In this example, we compare the strings of the earth and the heart.
public class AnagramCheck{
public static void main(String[] args) {
String str1 = "earth";
String str2 = "heart";
boolean isAnagram = areAnagrams(str1, str2);
if (isAnagram) {
System.out.println("The strings are anagrams.");
} else {
System.out.println("The strings are not anagrams.");
}
}
public static boolean areAnagrams(String str1, String str2) {
str1 = str1.replaceAll("\s", "").toLowerCase();
str2 = str2.replaceAll("\s", "").toLowerCase();
if (str1.length() != str2.length()) {
return false;
}
int[] charCount = new int[26];
for (char c : str1.toCharArray()) {
charCount[c - 'a']++;
}
for (char c : str2.toCharArray()) {
charCount[c - 'a']--;
if (charCount[c - 'a'] < 0) {
return false;
}
}
return true;
}
}
This program calculates the sum of the digits of a given number. In this example, we use number = 15092023. The program repeatedly extracts the last digit of the number using the modulo operator and adds it to a cumulative sum. It then removes the last digit by dividing the number by 10, continuing this process until all digits have been processed.
public class SumOfDigits {
public static void main(String[] args) {
int number = 15092023; // Number to calculate the sum of digits
int sum = sumOfDigits(number);
System.out.println("The sum of digits of " + number + " is: " + sum);
}
public static int sumOfDigits(int num) {
int sum = 0;
while (num != 0) {
sum += num % 10;
num /= 10;
}
return sum;
}
}
This program checks if a vowel is present in a given string. In this example, we check the string input "LearningHub." The program converts the string to lowercase and uses a regular expression to search for vowels (a, e, i, o, u). If a vowel is found, it returns true; otherwise, it returns false.
public class VowelCheck {
public static void main(String[] args) {
String input = "LearningHub"; // The string to check for vowels
boolean hasVowel = containsVowel(input);
if (hasVowel) {
System.out.println("The string contains a vowel.");
} else {
System.out.println("The string does not contain a vowel.");
}
}
public static boolean containsVowel(String str) {
return str.toLowerCase().matches(".*[aeiou].*");
}
}
This program checks if a given string is a palindrome. A palindrome is a string that reads the same backward as forward. In this example, we use the string input = "Eva, can I see bees in a cave?". The program first removes all non-alphanumeric characters and converts the string to lowercase. It then reverses the cleaned string and compares it to the original cleaned string. If they are equal, the string is a palindrome; otherwise, it is not.
public class PalindromeCheck {
public static void main(String[] args) {
String input = "Eva, can I see bees in a cave?"; // The string to check for palindrome
boolean isPalindrome = isPalindrome(input);
if (isPalindrome) {
System.out.println("The string is a palindrome.");
} else {
System.out.println("The string is not a palindrome.");
}
}
public static boolean isPalindrome(String str) {
str = str.replaceAll("[^a-zA-Z0-9]", "").toLowerCase();
String reversed = new StringBuilder(str).reverse().toString();
return str.equals(reversed);
}
}
This program converts a binary number to a decimal. In this example, the binary string 1101 is processed by iterating through each bit from right to left, adding the corresponding power of 2 for each '1'.
public class BinaryToDecimalLoop {
public static void main(String[] args) {
String binary = "1101"; // The binary number to convert
int decimal = binaryToDecimal(binary);
System.out.println("The decimal equivalent of binary " + binary + " is: " + decimal);
}
public static int binaryToDecimal(String binary) {
int decimal = 0;
int base = 1;
for (int i = binary.length() - 1; i >= 0; i--) {
if (binary.charAt(i) == '1') {
decimal += base;
}
base *= 2;
}
return decimal;
}
}
This program toggles the case of each character in a string. For the input leArnInGhUb, it converts lowercase letters to uppercase and vice versa, which results in LEaRNiNgHuB. The toggled string is then printed.
public class ToggleString {
public static void main(String[] args) {
String input = "leArnInGhUb"; // The string to toggle
String toggled = toggleCase(input);
System.out.println("Toggled string: " + toggled);
}
public static String toggleCase(String str) {
StringBuilder toggled = new StringBuilder();
for (char c : str.toCharArray()) {
if (Character.isLowerCase(c)) {
toggled.append(Character.toUpperCase(c));
} else {
toggled.append(Character.toLowerCase(c));
}
}
return toggled.toString();
}
}
This program converts a decimal number to its binary equivalent. In this example, the decimal number 13 is converted using the Integer.toBinaryString method, resulting in the binary representation 1101, which is then printed.
public class DecimalToBinary{
public static void main(String[] args) {
int decimal = 13; // The decimal number to convert
String binary = Integer.toBinaryString(decimal);
System.out.println("The binary equivalent of decimal " + decimal + " is: " + binary);
}
}
This program calculates the Nth Fibonacci number using iteration. In this example, for n = 6, it builds an array to store Fibonacci values up to the 6th term, resulting in the output 8, which is the 6th Fibonacci number.
public class FibonacciWithArray {
public static void main(String[] args) {
int n = 6; // The value of N for which to calculate the Fibonacci number
int result = fibonacci(n);
System.out.println("The " + n + "th Fibonacci number is: " + result);
}
public static int fibonacci(int n) {
if (n <= 1) {
return n;
}
int[] fibArray = new int[n + 1];
fibArray[0] = 0;
fibArray[1] = 1;
for (int i = 2; i <= n; i++) {
fibArray[i] = fibArray[i - 1] + fibArray[i - 2];
}
return fibArray[n];
}
}
This program prints all prime numbers up to a specified number. In this example, for number = 19, it identifies and displays the prime numbers by checking each odd number for primality, starting from 3. The output includes all primes up to 19, such as 2, 3, 5, 7, 11, 13, 17, 19.
public class PrimeNumbers{
public static void main(String[] args) {
int number = 19; // The number up to which to find prime numbers
System.out.println("Prime numbers up to " + number + ":");
printPrimes(number);
}
public static void printPrimes(int number) {
if (number >= 2) {
System.out.print(2 + " ");
}
for (int i = 3; i <= number; i += 2) {
if (isPrime(i)) {
System.out.print(i + " ");
}
}
}
public static boolean isPrime(int num) {
if (num < 2) return false;
if (num == 2) return true;
if (num % 2 == 0) return false;
for (int j = 3; j <= Math.sqrt(num); j += 2) {
if (num % j == 0) {
return false;
}
}
return true;
}
}
This program implements the Bubble Sort algorithm, which repeatedly steps through the array, compares adjacent elements, and swaps them if they are in the wrong order. In this example, the array [64, 34, 25, 12, 22, 11, 90] is sorted in ascending order, which results in [11, 12, 22, 25, 34, 64, 90].
import java.util.Arrays;
public class BubbleSort{
public static void main(String[] args) {
int[] array = {64, 34, 25, 12, 22, 11, 90};
bubbleSort(array);
System.out.println("Sorted array: " + Arrays.toString(array));
}
public static void bubbleSort(int[] array) {
int n = array.length;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (array[j] > array[j + 1]) {
// Swap array[j] and array[j + 1]
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
}
This program performs a Linear Search to find a target element in an array. The Linear Search algorithm checks each element sequentially until the target is found or the end of the array is reached. In this example, the target 4 is searched within the array [5, 3, 8, 4, 2].
public class LinearSearch {
public static void main(String[] args) {
int[] array = {5, 3, 8, 4, 2};
int target = 4;
int result = linearSearch(array, target, 0);
if (result != -1) {
System.out.println("Element found at index: " + result);
} else {
System.out.println("Element not found");
}
}
public static int linearSearch(int[] array, int target, int index) {
if (index >= array.length) {
return -1;
}
if (array[index] == target) {
return index;
}
return linearSearch(array, target, index + 1);
}
}
This program implements the Binary Search algorithm to find a target element in a sorted array. Binary Search works by repeatedly dividing the search interval in half, comparing the target to the middle element, and narrowing down the search to either the left or right half of the array. In this example, the target 10 is searched within the sorted array [2, 3, 4, 10, 40].
public class BinarySearch {
public static void main(String[] args) {
int[] array = {2, 3, 4, 10, 40};
int target = 10;
int result = binarySearch(array, target, 0, array.length - 1);
if (result != -1) {
System.out.println("Element found at index: " + result);
} else {
System.out.println("Element not found");
}
}
public static int binarySearch(int[] array, int target, int left, int right) {
if (right >= left) {
int mid = left + (right - left) / 2;
if (array[mid] == target) {
return mid;
} else if (array[mid] > target) {
return binarySearch(array, target, left, mid - 1);
} else {
return binarySearch(array, target, mid + 1, right);
}
}
return -1;
}
}
This program finds the second largest number in an array by iterating through its elements. It keeps track of the largest and second-largest numbers using two variables. In this example, the array [34, 25, 12, 22, 11, 90] is processed to determine the second largest value.
public class SecondLargestInArray {
public static void main(String[] args) {
int[] array = {34, 25, 12, 22, 11, 90};
int secondLargest = findSecondLargest(array);
if (secondLargest != Integer.MIN_VALUE) {
System.out.println("The second largest number is: " + secondLargest);
} else {
System.out.println("There is no second largest number in the array.");
}
}
public static int findSecondLargest(int[] array) {
int largest = Integer.MIN_VALUE;
int secondLargest = Integer.MIN_VALUE;
for (int num : array) {
if (num > largest) {
secondLargest = largest;
largest = num;
} else if (num > secondLargest && num < largest) {
secondLargest = num;
}
}
return secondLargest;
}
}
This program shuffles an array randomly using the Fisher-Yates algorithm. By iterating from the end of the array to the beginning and swapping each element with a randomly selected element, the array [1, 2, 3, 4, 5, 6] is randomized.
import java.util.Arrays;
import java.util.Random;
public class ArrayShuffle{
public static void main(String[] args) {
int[] array = {1, 2, 3, 4, 5, 6};
shuffleArray(array);
System.out.println("Shuffled array: " + Arrays.toString(array));
}
public static void shuffleArray(int[] array) {
Random random = new Random();
for (int i = array.length - 1; i > 0; i--) {
int j = random.nextInt(i + 1);
// Swap elements
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
This program calculates the sum of all elements in an integer array. It goes through each number in the array [25, 12, 22, 11, 90] and calculates the total sum of these numbers.
public class SumOfArrayElements {
public static void main(String[] args) {
int[] array = {25, 12, 22, 11, 90};
int sum = calculateSum(array);
System.out.println("The sum of all elements in the array is: " + sum);
}
public static int calculateSum(int[] array) {
int sum = 0;
for (int num : array) {
sum += num;
}
return sum;
}
}
This program finds the common numbers between two arrays. It creates a set from the first array to store its numbers and then checks which of those numbers are also in the second array. In this example, it uses the arrays [1, 2, 2, 1] and [2, 2] to find the common elements.
import java.util.Arrays;
import java.util.HashSet;
public class ArrayIntersection{
public static void main(String[] args) {
int[] array1 = {1, 2, 2, 1};
int[] array2 = {2, 2};
int[] intersection = findIntersection(array1, array2);
System.out.print("Intersection: ");
for (int num : intersection) {
System.out.print(num + " ");
}
}
public static int[] findIntersection(int[] array1, int[] array2) {
HashSet<Integer> set = new HashSet<>();
for (int num : array1) {
set.add(num);
}
return Arrays.stream(array2)
.filter(set::contains)
.distinct()
.toArray();
}
}
This program counts how many times each character appears in a given string. It uses an array to keep track of the counts for all possible ASCII characters. In this example, it analyzes the string 'LearningHub' and displays the number of occurrences for each character.
public class CharacterCount{
public static void main(String[] args) {
String input = "LearningHub";
countCharacterOccurrences(input);
}
public static void countCharacterOccurrences(String input) {
int[] charCount = new int[256]; // Assuming ASCII characters
for (char c : input.toCharArray()) {
charCount[c]++;
}
System.out.println("Character occurrences:");
for (int i = 0; i < charCount.length; i++) {
if (charCount[i] > 0) {
System.out.println((char) i + ": " + charCount[i]);
}
}
}
}
This program calculates the length of the longest substring in a given string that does not contain repeating characters. It uses an array to track the last index of each character and updates the starting point of the substring as needed. In this example, the input is 'learninghub', and the program determines the length of the longest substring without any repeated characters.
public class LongestSubstring {
public static void main(String[] args) {
String input = "learninghub";
int length = lengthOfLongestSubstring(input);
System.out.println("Input: " + input);
System.out.println("Length of longest substring without repeating characters: " + length);
}
public static int lengthOfLongestSubstring(String s) {
int[] lastIndex = new int[256]; // Assuming ASCII characters
for (int i = 0; i < lastIndex.length; i++) {
lastIndex[i] = -1;
}
int maxLength = 0;
int start = 0;
for (int i = 0; i < s.length(); i++) {
if (lastIndex[s.charAt(i)] >= start) {
start = lastIndex[s.charAt(i)] + 1;
}
lastIndex[s.charAt(i)] = i;
maxLength = Math.max(maxLength, i - start + 1);
}
return maxLength;
}
}
This program removes all occurrences of a specified character from a given string. It converts the string into a character array and builds a new string by appending only the characters that do not match the specified character.
In this example, the input is 'LearningHub', and the character 'a' is removed, resulting in 'LerningHub'.
public class RemoveChar{
public static void main(String[] args) {
String input = "LearningHub";
char charToRemove = 'a';
String result = removeCharacter(input, charToRemove);
System.out.println("Original: " + input);
System.out.println("After removal: " + result);
}
public static String removeCharacter(String input, char charToRemove) {
char[] characters = input.toCharArray();
StringBuilder result = new StringBuilder();
for (char c : characters) {
if (c != charToRemove) {
result.append(c);
}
}
return result.toString();
}
}
This program removes duplicate values from an array of integers. It first sorts the array to bring duplicate elements together. Then, it iterates through the sorted array, adding unique elements to a temporary array.
Finally, it returns a new array containing the unique values. In this example, the input array [8, 2, 3, 2, 8, 3, 5, 1] results in an array with unique values.
import java.util.Arrays;
public class RemoveDuplicates{
public static void main(String[] args) {
int[] array = {8, 2, 3, 2, 8, 3, 5, 1};
int[] result = removeDuplicates(array);
System.out.println("Array after removing duplicates: " + Arrays.toString(result));
}
public static int[] removeDuplicates(int[] array) {
Arrays.sort(array);
int n = array.length;
if (n == 0) return new int[0];
int[] temp = new int[n];
int j = 0;
for (int i = 0; i < n - 1; i++) {
if (array[i] != array[i + 1]) {
temp[j++] = array[i];
}
}
temp[j++] = array[n - 1];
return Arrays.copyOf(temp, j);
}
}
This program merges two sorted arrays into a single sorted array. It compares elements from each array using two pointers, adding the smaller element to the new array and moving the pointer forward. Once all elements from one array are added, it appends the remaining elements from the other array. In this example, the input arrays are [12, 31, 25, 72] and [25, 42, 16, 38], and the program merges them into a single sorted array.
import java.util.Arrays;
public class MergeSortedArrays{
public static void main(String[] args) {
int[] array1 = {12, 31, 25, 72};
int[] array2 = {25, 42, 16, 38};
int[] mergedArray = mergeSortedArrays(array1, array2);
System.out.println("Merged Array: " + Arrays.toString(mergedArray));
}
public static int[] mergeSortedArrays(int[] array1, int[] array2) {
int n1 = array1.length;
int n2 = array2.length;
int[] mergedArray = new int[n1 + n2];
int i = 0, j = 0, k = 0;
while (i < n1 && j < n2) {
if (array1[i] < array2[j]) {
mergedArray[k++] = array1[i++];
} else {
mergedArray[k++] = array2[j++];
}
}
while (i < n1) {
mergedArray[k++] = array1[i++];
}
while (j < n2) {
mergedArray[k++] = array2[j++];
}
return mergedArray;
}
}
This program rotates an array to the right by a specified number of steps. It first calculates the effective steps by taking the remainder when the step count is divided by the array's length.
To perform the rotation, it reverses the entire array, then reverses the first part (up to the step count) and the remaining part separately. In this example, the input array is [1, 2, 3, 4, 5] with a rotation of 2 steps.
import java.util.Arrays;
public class ArrayRotation {
public static void main(String[] args) {
int[] array = {1, 2, 3, 4, 5};
int steps = 2;
System.out.println("Original array: " + Arrays.toString(array));
rotateArray(array, steps);
System.out.println("Array after rotation: " + Arrays.toString(array));
}
public static void rotateArray(int[] array, int steps) {
int n = array.length;
steps = steps % n;
reverseArray(array, 0, n - 1);
reverseArray(array, 0, steps - 1);
reverseArray(array, steps, n - 1);
}
private static void reverseArray(int[] array, int start, int end) {
while (start < end) {
int temp = array[start];
array[start] = array[end];
array[end] = temp;
start++;
end--;
}
}
}
This program demonstrates a Divide by 0 exception in Java. It defines a numerator and sets the denominator to zero. When attempting to divide by zero, an ArithmeticException is thrown. The program catches this exception and prints an appropriate message that division by zero is not allowed.
public class DivideByZero{
public static void main(String[] args) {
int numerator = 40;
int denominator = 0;
try {
int result = numerator / denominator;
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Exception caught: Cannot divide by zero!");
}
}
}
This program demonstrates inheritance in a simple employee management system. The base class, Employee, represents general employee details and behavior. Two subclasses, Developer and Manager, inherit from Employee and add specific details for each role. The developer includes a programming language, while the Manager has a team size. Each subclass overrides the work method to define role-specific tasks.
In this example, a Developer named Harry codes in Java, and a Manager named Dumbledore manages a team of 5.
class Employee {
protected String name;
protected String role;
public Employee(String name, String role) {
this.name = name;
this.role = role;
}
public void work() {
System.out.println(name + " is working as a " + role + ".");
}
public void displayInfo() {
System.out.println("Employee Name: " + name + ", Role: " + role);
}
}
class Developer extends Employee {
private String programmingLanguage;
public Developer(String name, String programmingLanguage) {
super(name, "Developer");
this.programmingLanguage = programmingLanguage;
}
@Override
public void work() {
System.out.println(name + " is coding in " + programmingLanguage + ".");
}
}
class Manager extends Employee {
private int teamSize;
public Manager(String name, int teamSize) {
super(name, "Manager");
this.teamSize = teamSize;
}
@Override
public void work() {
System.out.println(name + " is managing a team of " + teamSize + " developers.");
}
}
public class EmployeeManagement{
public static void main(String[] args) {
Employee developer = new Developer("Harry", "Java");
Employee manager = new Manager("Dumbledore", 5);
developer.displayInfo();
developer.work();
manager.displayInfo();
manager.work();
}
}
This program demonstrates a custom exception called UserNotFoundException for a user management system. The UserManagement class checks if a username exists in its list; if not, it throws a UserNotFoundException.
In the main method, this exception is triggered for a non-existent user, displaying an error message.
class UserNotFoundException extends Exception {
public UserNotFoundException(String message) {
super(message);
}
}
class UserManagement {
private String[] users = {"Harry", "Rob", "Hermione"};
public void findUser(String username) throws UserNotFoundException {
boolean userFound = false;
for (String user : users) {
if (user.equalsIgnoreCase(username)) {
userFound = true;
break;
}
}
if (!userFound) {
throw new UserNotFoundException("User not found: " + username);
}
System.out.println("User " + username + " found in the system.");
}
}
public class CustomExceptionExample {
public static void main(String[] args) {
UserManagement userManagement = new UserManagement();
try {
userManagement.findUser("Harry");
userManagement.findUser("Rob");
// This will throw a UserNotFoundException
userManagement.findUser("Draco");
} catch (UserNotFoundException e) {
System.out.println("Exception caught: " + e.getMessage());
}
}
}
This program illustrates multithreading by using isAlive() and join(). It creates two TaskThread instances, each simulating a task. The main thread monitors their statuses with isAlive() to check if they are running. Once both tasks are finished, join() is called to ensure the main thread waits for their completion before displaying a final message.
class TaskThread extends Thread {
private String taskName;
public TaskThread(String taskName) {
this.taskName = taskName;
}
@Override
public void run() {
System.out.println(taskName + " is starting.");
try {
Thread.sleep((int) (Math.random() * 2000));
} catch (InterruptedException e) {
System.out.println(taskName + " was interrupted.");
}
System.out.println(taskName + " has completed.");
}
}
public class ThreadStatusExample {
public static void main(String[] args) throws InterruptedException {
TaskThread thread1 = new TaskThread("Task 1");
TaskThread thread2 = new TaskThread("Task 2");
thread1.start();
thread2.start();
while (thread1.isAlive() || thread2.isAlive()) {
if (thread1.isAlive()) {
System.out.println(thread1.getName() + " is still running.");
} else {
System.out.println(thread1.getName() + " has finished.");
}
if (thread2.isAlive()) {
System.out.println(thread2.getName() + " is still running.");
} else {
System.out.println(thread2.getName() + " has finished.");
}
Thread.sleep(500);
}
thread1.join();
thread2.join();
System.out.println("Both tasks are complete.");
}
}
This program demonstrates thread synchronization using a shared resource, TestReport. Multiple TestCaseThread instances execute concurrently, each adding a test result to the shared report. The addResult method is synchronized to prevent data inconsistency caused by concurrent access.
After all threads finish, the main thread prints the execution report.
import java.util.ArrayList;
import java.util.List;
class TestReport {
private List<String> results = new ArrayList<>();
public synchronized void addResult(String result) {
results.add(result);
}
public void printReport() {
System.out.println("Test Execution Report:");
for (String result : results) {
System.out.println(result);
}
}
}
class TestCaseThread extends Thread {
private TestReport report;
private String testName;
public TestCaseThread(TestReport report, String testName) {
this.report = report;
this.testName = testName;
}
@Override
public void run() {
try {
Thread.sleep((int) (Math.random() * 1000));
report.addResult(testName + " executed successfully.");
} catch (InterruptedException e) {
report.addResult(testName + " execution failed due to interruption.");
}
}
}
public class ThreadSynchronizationTest {
public static void main(String[] args) throws InterruptedException {
TestReport report = new TestReport();
Thread test1 = new TestCaseThread(report, "Test Case 1");
Thread test2 = new TestCaseThread(report, "Test Case 2");
Thread test3 = new TestCaseThread(report, "Test Case 3");
Thread test4 = new TestCaseThread(report, "Test Case 4");
test1.start();
test2.start();
test3.start();
test4.start();
// Waiting for all test threads to finish
test1.join();
test2.join();
test3.join();
test4.join();
report.printReport();
}
}
This program computes the transpose of a matrix. It defines a method called transposeMatrix that takes a 2D integer array (the original matrix) and returns its transposed version, where the rows and columns are swapped.
The main method initializes a sample 3x3 matrix, prints it, then computes and prints its transpose using the helper method printMatrix to display both matrices.
public class MatrixTranspose {
public static int[][] transposeMatrix(int[][] matrix) {
int rows = matrix.length;
int cols = matrix[0].length;
int[][] transposed = new int[cols][rows];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
transposed[j][i] = matrix[i][j];
}
}
return transposed;
}
public static void main(String[] args) {
int[][] originalMatrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
System.out.println("Original Matrix:");
printMatrix(originalMatrix);
int[][] transposedMatrix = transposeMatrix(originalMatrix);
System.out.println("
Transposed Matrix:");
printMatrix(transposedMatrix);
}
public static void printMatrix(int[][] matrix) {
for (int[] row : matrix) {
for (int value : row) {
System.out.print(value + " ");
}
System.out.println();
}
}
}
This program implements the selection sort algorithm to sort an array of integers. The selectionSort method iterates through the array, repeatedly selecting the smallest element from the unsorted portion and swapping it with the first unsorted element. The main method initializes an array of execution times, prints the unsorted array, then applies the selection sort and prints the sorted array.
public class SelectionSort {
public static void selectionSort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
int temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp;
}
}
public static void main(String[] args) {
int[] testTimes = {45, 23, 89, 12, 78, 55};
System.out.println("Unsorted execution times:");
for (int time : testTimes) {
System.out.print(time + " ");
}
selectionSort(testTimes);
System.out.println("
Sorted execution times:");
for (int time : testTimes) {
System.out.print(time + " ");
}
}
}
This program solves a Sudoku puzzle by filling empty cells in the grid. It checks each empty cell and tries placing numbers from one to nine. For each number, it checks if the placement is valid according to Sudoku rules. If valid, it proceeds to the next cell. If not, it backtracks and tries another number.
This process continues until the puzzle is solved.
class SudokuSolver
{
public static boolean isValid(int[][] grid, int row, int col, int value)
{
for (int i = 0; i < grid.length; i++)
{
if (grid[row][i] == value) {
return false;
}
}
for (int j = 0; j < grid.length; j++)
{
if (grid[j][col] == value) {
return false;
}
}
int sqrt = (int) Math.sqrt(grid.length);
int startRow = row - row % sqrt;
int startCol = col - col % sqrt;
for (int i = startRow; i < startRow + sqrt; i++)
{
for (int j = startCol; j < startCol + sqrt; j++)
{
if (grid[i][j] == value) {
return false;
}
}
}
return true;
}
public static boolean solvePuzzle(int[][] grid, int size)
{
int row = -1;
int col = -1;
boolean emptyCell = true;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
if (grid[i][j] == 0)
{
row = i;
col = j;
emptyCell = false;
break;
}
}
if (!emptyCell) {
break;
}
}
if (emptyCell)
{
return true;
}
for (int num = 1; num <= size; num++)
{
if (isValid(grid, row, col, num))
{
grid[row][col] = num;
if (solvePuzzle(grid, size))
{
return true;
}
else
{
grid[row][col] = 0;
}
}
}
return false;
}
public static void display(int[][] grid, int size)
{
for (int r = 0; r < size; r++)
{
for (int d = 0; d < size; d++)
{
System.out.print(grid[r][d]);
System.out.print(" ");
}
System.out.println();
}
}
public static void main(String args[])
{
int[][] grid = new int[][] {
{5, 3, 0, 0, 7, 0, 0, 0, 0},
{6, 0, 0, 1, 9, 5, 0, 0, 0},
{0, 9, 8, 0, 0, 0, 0, 6, 0},
{8, 0, 0, 0, 6, 0, 0, 0, 3},
{4, 0, 0, 8, 0, 3, 0, 0, 1},
{7, 0, 0, 0, 2, 0, 0, 0, 6},
{0, 6, 0, 0, 0, 0, 2, 8, 0},
{0, 0, 0, 4, 1, 9, 0, 0, 5},
{0, 0, 0, 0, 8, 0, 0, 7, 9}
};
int size = grid.length;
if (solvePuzzle(grid, size))
{
System.out.println("
Solved Sudoku grid:");
display(grid, size);
}
else
{
System.out.println("No solution found");
}
}
}
This program implements a simple calculator that performs addition, subtraction, multiplication, and division. It prompts the user to enter two numbers and an operation symbol. Based on the operation, it calls the appropriate method to calculate the result and displays it.
If the division operation is selected and the second number is zero, the program outputs an error message to prevent division by zero.
import java.util.Scanner;
public class SimpleCalculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the first number: ");
double num1 = scanner.nextDouble();
System.out.print("Enter the second number: ");
double num2 = scanner.nextDouble();
System.out.print("Enter an operation (+, -, *, /): ");
char operation = scanner.next().charAt(0);
double result;
switch (operation) {
case '+':
result = add(num1, num2);
System.out.println("Result: " + result);
break;
case '-':
result = subtract(num1, num2);
System.out.println("Result: " + result);
break;
case '*':
result = multiply(num1, num2);
System.out.println("Result: " + result);
break;
case '/':
if (num2 != 0) {
result = divide(num1, num2);
System.out.println("Result: " + result);
} else {
System.out.println("Error: Division by zero is not allowed.");
}
break;
default:
System.out.println("Error: Invalid operation.");
break;
}
scanner.close();
}
public static double add(double a, double b) {
return a + b;
}
public static double subtract(double a, double b) {
return a - b;
}
public static double multiply(double a, double b) {
return a * b;
}
public static double divide(double a, double b) {
return a / b;
}
}
This program prints Floyd's Triangle. Floyd's Triangle is a triangular array of natural numbers. In this example, it shows four lines of the triangle.
public class FloydsTriangle {
public static void main(String[] args) {
int rows = 4;
int number = 1;
System.out.println("Floyd's Triangle:");
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(number + " ");
number++;
}
System.out.println();
}
}
}
This program finds all prime numbers up to a specified limit using the Sieve of Eratosthenes algorithm. It initializes an array to track prime numbers and marks non-prime multiples. In this example, the limit is set to 50, and the program prints all prime numbers up to that limit.
import java.util.Arrays;
public class SieveOfEratosthenes {
public static void main(String[] args) {
int limit = 50;
boolean[] isPrime = new boolean[limit + 1];
Arrays.fill(isPrime, true);
isPrime[0] = false;
isPrime[1] = false;
// Sieve of Eratosthenes algorithm
for (int p = 2; p * p <= limit; p++) {
if (isPrime[p]) {
for (int multiple = p * p; multiple <= limit; multiple += p) {
isPrime[multiple] = false;
}
}
}
System.out.println("Prime numbers up to " + limit + ":");
for (int number = 2; number <= limit; number++) {
if (isPrime[number]) {
System.out.print(number + " ");
}
}
}
}
In conclusion, preparing for Java interviews is an important step in becoming a Java developer. This guide provides a set of interview questions for Java developers at basic to experienced levels. By exploring these questions, you can deepen your understanding of key concepts and prepare effectively for various stages of the interview process.
Did you find this page helpful?
Try LambdaTest Now !!
Get 100 minutes of automation test minutes FREE!!